package edu.neu.cs6515.test;

import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import edu.neu.cs6515.admin.Administrator;
import edu.neu.cs6515.admin.RankingEntry;
import edu.neu.cs6515.hci.HCIPanel;
import edu.neu.cs6515.hci.HCIStrategy;
import edu.neu.cs6515.player.AbstractStrategyPlayer;
import edu.neu.cs6515.player.Player;
import edu.neu.cs6515.player.strategy.AbstractStrategy;
import edu.neu.cs6515.player.strategy.GreedyStrategy;
import edu.neu.cs6515.player.strategy.LowestColorFirstStrategy;
import edu.neu.cs6515.player.strategy.RandomStrategy;

/**
 * farm that run a game for human player and random AI players
 */
public final class IngeniousGameForOneHumanRunner {

    /**
     * private C'tor to prevent mis-override in subclass
     */
    private IngeniousGameForOneHumanRunner() {

    }

    /**
	 * @param args
	 *            arguments for main
	 * @throws InvocationTargetException
	 */
	public static void main(final String[] args) throws InterruptedException,
			InvocationTargetException {
		if (args.length == 0) {
			final HCIPanel hciFrame = new HCIPanel(60);
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					JFrame frame = new JFrame();
					frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
					frame.setContentPane(hciFrame);
					frame.setSize(800, 800);
					frame.setLocation(100, 100);
					frame.setVisible(true);
				}
			});
			setUpAGameForHuman(hciFrame);


        } else {
            setUpAGameForRandomAIPlayers(Integer.valueOf(args[0]));
        }
    }

    /**
     * set up a game for given number of AI players
     * 
     * @param nbrOfPlayer
     *            number of AI players in game
     */
    private static void setUpAGameForRandomAIPlayers(final int nbrOfPlayer) {
        int number = nbrOfPlayer;
        List<AbstractStrategyPlayer> listOfPlayer = new LinkedList<AbstractStrategyPlayer>();
        while (number-- > 0) {
            AbstractStrategy strategy = getStrategyRandomly();
            listOfPlayer.add(new Player("player"
                    + number, strategy));
        }
        runGameWithPlayers(listOfPlayer);
    }

    /**
     * set up a game for human player
     */
    public static void setUpAGameForHuman(HCIPanel hciFrame) {
        List<AbstractStrategyPlayer> gamePlayers = new LinkedList<AbstractStrategyPlayer>();
        int numberOfAIPlayers = new Random().nextInt(3) + 1;
        System.out.println("numberOfAIPlayers"
                + numberOfAIPlayers);
        for (int i = 0; i < numberOfAIPlayers; i++) {
            gamePlayers.add(new Player("Player"
                    + i, getStrategyRandomly()));
        }
        gamePlayers.add(new Player("humanPlayer",
                new HCIStrategy(60, hciFrame)));
        runGameWithPlayers(gamePlayers);
    }

    /**
     * run a complete ingenious game by given list of players
     * 
     * @param gamePlayers
     *            to player the game
     */
    private static void runGameWithPlayers(final List<AbstractStrategyPlayer> gamePlayers) {
        Administrator gameAdmin = new Administrator(gamePlayers.size());
        for (AbstractStrategyPlayer player : gamePlayers) {
            gameAdmin.registerPlayer(player,
                    player.getPlayersName());
        }
        System.out.println("players added ready to run game");
        List<RankingEntry> gameResults = gameAdmin.runGame();
        System.out.println("game results:");
        for (RankingEntry rankingEntry : gameResults) {
            System.out.println(rankingEntry);
        }
        System.out.println("---------");
    }

    /**
     * randomly get one of GreedyStrategy, LowestScoreFirstStrategy or
     * RandomStrategy
     * 
     * @return the strategy
     */
    private static AbstractStrategy getStrategyRandomly() {
        int rand = new Random().nextInt(3);
        switch (rand) {
        case 0:
            return new RandomStrategy();
        case 1:
            return new LowestColorFirstStrategy();
        default:
            return new GreedyStrategy();
        }
    }
}
